#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <math.h>
#include <limits.h>
#include <time.h>
#include "main.h"

// N is now the array holding Bell user packets
// M is now the array holding Techsavy user packets
// So yes, we are assumeing one source now (say youtube)
struct packet *N, *M; //, *Y, *Z;


// vvvv  these are the variable we want to change and study their effect
int NUM_OF_PACKET_PER_TEX_USER=100; // number of packets requested by each techsavy user
                                    // The effect of capping is that this number will increase in simulation
int NUM_OF_PACKET_PER_BELL_USER=10; // number of packets requested by each bell user
				   // This number is fixed throughout because they are allways capped


int 	NUM_BELL_PACKETS;
int 	NUM_TEX_PACKETS;

/** @fn mux
 * @brief merges streams of packets into one
 * @callergraph
 *
 * @return total number of packets in the final array
 */
int mux(struct packet *M, struct packet *N, struct packet *Y, struct packet *Z, struct packet *packetArray) {
    int totalNumberOfPackets = 0; //!< as each packet is muxed, this is incremented

    int Tindx = 0;
    int Bindx = 0;

    while ((Tindx + Bindx) < (NUM_USER_PER_DSLAM * NUM_TEX_DSLAM * NUM_OF_PACKET_PER_TEX_USER + NUM_USER_PER_DSLAM * NUM_BELL_DSLAM * NUM_OF_PACKET_PER_BELL_USER)) {
        // This is the case where we flip a coin between Techsavy and Bell customers
        // But in reality this shouldn't be the case at the router
        // because we don't know what provider the users are with at this stage.
        // So the sensible thing to do is just serve them one at a time which is
        // what the second code section (uncommented) below does.


        // here we are assuming that at the router we do not know anything about what provider
        // (techsavy or bell) is the packet related to. The assumption here is that the router
        // (which is basically the same as servers, e.g. youtube) servers the users one packet
        // at a time regardless of their low-end provider. The following assignment/muxing assumes
        // also that users have made reqeusts in the order of user1 user2 ....


        // randomly pick one of the streams
        int streamSelect = rand() % (NUM_TEX_DSLAM + NUM_BELL_DSLAM);
        // extract packet from the randomly selected stream and add to packet array
        if (streamSelect < NUM_TEX_DSLAM) {
            //printf("Tex ");
            if (Tindx < NUM_USER_PER_DSLAM * NUM_TEX_DSLAM * NUM_OF_PACKET_PER_TEX_USER) {
                packetArray[totalNumberOfPackets] = M[Tindx];
                Tindx++;
                totalNumberOfPackets++;
            }
        } else {
            //printf("Bell ");
            if (Bindx < NUM_USER_PER_DSLAM * NUM_BELL_DSLAM * NUM_OF_PACKET_PER_BELL_USER) {
                packetArray[totalNumberOfPackets] = N[Bindx];
                Bindx++;
                totalNumberOfPackets++;
            }
        }
    }

    int TOTAL_NUM_OF_PACKETS = totalNumberOfPackets;
    totalNumberOfPackets = 0;
    while (totalNumberOfPackets < TOTAL_NUM_OF_PACKETS) {
        Time tv;
        gettimeofday(&tv, NULL);
        packetArray[totalNumberOfPackets].internetDispatchTime = tv;
        totalNumberOfPackets++;
    }

    return totalNumberOfPackets;
}


void initializePacketArrayForEachService() {
    M = (struct packet*) malloc(NUM_USER_PER_DSLAM*NUM_TEX_DSLAM*NUM_OF_PACKET_PER_TEX_USER*sizeof(struct packet));
    if (M == NULL)
        printf("DONE");
    //Y = (struct packet*) malloc(MAX_NUM_YOUTUBE_USER_PACKETS*sizeof(struct packet));
    //Z = (struct packet*) malloc(MAX_NUM_ZSHARE_USER_PACKETS*sizeof(struct packet));
    N = (struct packet*) malloc(NUM_USER_PER_DSLAM*NUM_BELL_DSLAM*NUM_OF_PACKET_PER_BELL_USER*sizeof(struct packet));
    if (N == NULL)
        printf("DONE");
    
}
void initializeEverythingElseForAllServices() {
    int packetCounter = 0;
    Time tv;
    struct packet* temp;

    int UserCounter = 0, dslamCounter = 0, brasCounter = 0;
    for (packetCounter = 0; packetCounter < NUM_USER_PER_DSLAM * NUM_TEX_DSLAM * NUM_OF_PACKET_PER_TEX_USER; packetCounter++) {
        temp = M + packetCounter;
        temp->source = 'T';
        temp->userNumber = UserCounter;
        temp->dslamNumber = dslamCounter;
        temp->brasNumber = brasCounter;

        UserCounter++;
        if (UserCounter == NUM_USER_PER_DSLAM) {
            dslamCounter++;
            UserCounter = 0;
        }
        if (dslamCounter == NUM_TEX_DSLAM) {
            brasCounter++;
            dslamCounter = 0;
        }
        if (brasCounter == NUM_BRAS) {
            brasCounter = 0;
        }

        //gettimeofday(&tv, NULL);
        //temp->internetDispatchTime = tv;
    }

    UserCounter = 0;
    dslamCounter = NUM_TEX_DSLAM;
    brasCounter = 0;
    for (packetCounter = 0; packetCounter < NUM_USER_PER_DSLAM * NUM_BELL_DSLAM * NUM_OF_PACKET_PER_BELL_USER; packetCounter++) {
        temp = N + packetCounter;
        temp->source = 'B';
        temp->userNumber = UserCounter;
        temp->dslamNumber = dslamCounter+NUM_TEX_DSLAM;
        temp->brasNumber = brasCounter;

        UserCounter++;
        if (UserCounter == NUM_USER_PER_DSLAM) {
            dslamCounter++;
            UserCounter = 0;
        }
        if (dslamCounter == NUM_BELL_DSLAM) {
            brasCounter++;
            dslamCounter = 0;
        }
        if (brasCounter == NUM_BRAS) {
            brasCounter = 0;
        }

        //gettimeofday(&tv, NULL);
        //temp->internetDispatchTime = tv;
    }

}

/*
void initializeEverythingElseForAllServices() {
    int packetCounter = 0;
    Time tv;
        struct packet* temp;
        
    int UserCounter = 0, dslamCounter = 0, brasCounter = 0;
    for (packetCounter = 0; packetCounter < MAX_NUM_MEGAVIDEO_USER_PACKETS; packetCounter++) {
        temp = M + packetCounter;
        temp->source = 'M';
        temp->userNumber = UserCounter;
        temp->dslamNumber = dslamCounter;
        temp->brasNumber = brasCounter;
       
        UserCounter++;
        if(UserCounter == NUM_USER) {
           dslamCounter++;
           UserCounter=0;
        }
        if(dslamCounter == NUM_DSLAM) {
           brasCounter++;
           dslamCounter=0;
        }
        if(brasCounter == NUM_BRAS) {
           brasCounter=0;
        }

        //gettimeofday(&tv, NULL);
        //temp->internetDispatchTime = tv;
    }
    
    UserCounter = 0; dslamCounter = 0; brasCounter = 0;
    for (packetCounter = 0; packetCounter < MAX_NUM_NETFLIX_USER_PACKETS; packetCounter++) {
        temp = N + packetCounter;
        temp->source = 'N';
        temp->userNumber = UserCounter;
        temp->dslam`Number = dslamCounter;
        temp->brasNumber = brasCounter;
       
        UserCounter++;
        if(UserCounter == NUM_USER) {
           dslamCounter++;
           UserCounter=0;
        }
        if(dslamCounter == NUM_DSLAM) {
           brasCounter++;
           dslamCounter=0;
        }
        if(brasCounter == NUM_BRAS) {
           brasCounter=0;
        }

        //gettimeofday(&tv, NULL);
        //temp->internetDispatchTime = tv;
    }
    
    UserCounter = 0; dslamCounter = 0; brasCounter = 0;
    for (packetCounter = 0; packetCounter < MAX_NUM_YOUTUBE_USER_PACKETS; packetCounter++) {
        temp = Y + packetCounter;
        temp->source = 'Y';
        temp->userNumber = UserCounter;
        temp->dslamNumber = dslamCounter;
        temp->brasNumber = brasCounter;
       
        UserCounter++;
        if(UserCounter == NUM_USER) {
           dslamCounter++;
           UserCounter=0;
        }
        if(dslamCounter == NUM_DSLAM) {
           brasCounter++;
           dslamCounter=0;
        }
        if(brasCounter == NUM_BRAS) {
           brasCounter=0;
        }

        //gettimeofday(&tv, NULL);
        //temp->internetDispatchTime = tv;
    }
    
    UserCounter = 0; dslamCounter = 0; brasCounter = 0;
    for (packetCounter = 0; packetCounter < MAX_NUM_ZSHARE_USER_PACKETS; packetCounter++) {
        temp = Z + packetCounter;
        temp->source = 'Z';
        temp->userNumber = UserCounter;
        temp->dslamNumber = dslamCounter;
        temp->brasNumber = brasCounter;
       
        UserCounter++;
        if(UserCounter == NUM_USER) {
           dslamCounter++;
           UserCounter=0;
        }
        if(dslamCounter == NUM_DSLAM) {
           brasCounter++;
           dslamCounter=0;
        }
        if(brasCounter == NUM_BRAS) {
           brasCounter=0;
        }

        //gettimeofday(&tv, NULL);
        //temp->internetDispatchTime = tv;
    }
}*/

void printServiceLists() {
    int packetCounter = 0;
        struct packet *temp;
        FILE * pFile;

        pFile = fopen ("Megavideo.txt","w");
    fprintf(pFile, "User list for Megavideo: \n");
    for (packetCounter = 0; packetCounter < MAX_NUM_MEGAVIDEO_USER_PACKETS; packetCounter++) {
        temp = M + packetCounter;
        fprintf(pFile, "dispatchTime(s): %d\t\t dispatchTime(us): %d\t\t source: %c\t BRAS: %d\t DSLAM: %d\t User: %d\n", 
                                        temp->internetDispatchTime.tv_sec, temp->internetDispatchTime.tv_usec, temp->source, temp->brasNumber, temp->dslamNumber, temp->userNumber);
    }
    fclose (pFile);

    pFile = fopen ("Netflix.txt","w");
    fprintf(pFile, "User list for Netflix: \n");
    for (packetCounter = 0; packetCounter < MAX_NUM_NETFLIX_USER_PACKETS; packetCounter++) {
        temp = N + packetCounter;
        fprintf(pFile, "dispatchTime(s): %d\t\t dispatchTime(us): %d\t\t source: %c\t BRAS: %d\t DSLAM: %d\t User: %d\n", 
                                        temp->internetDispatchTime.tv_sec, temp->internetDispatchTime.tv_usec, temp->source, temp->brasNumber, temp->dslamNumber, temp->userNumber);
    }
    fclose (pFile);

}

void printMuxedArrayInternet(struct packet *muxedPacketArray, int totalNumberOfPackets)
{
        int packetCounter = 0;
        struct packet *temp;
        FILE * pFile;
        pFile = fopen ("ALL.txt","w");
        
        for (packetCounter = 0; packetCounter < totalNumberOfPackets; packetCounter++) 
        {
        temp = muxedPacketArray + packetCounter;
        fprintf(pFile, "dispatchTime(s): %d\t\t dispatchTime(us): %d\t\t source: %c\t\t BRAS: %d\t DSLAM: %d\t User: %d\n", 
                                        temp->internetDispatchTime.tv_sec, temp->internetDispatchTime.tv_usec, temp->source, temp->brasNumber, temp->dslamNumber, temp->userNumber);
    }
    fclose (pFile);
}

void lindleysRouter(struct packet * stream, const Time servicetime, int buffersize, int num_Packets) {

    struct packet *stream_ptr;    // points to a packet in the incoming stream of packets
    struct packet *buffer_first; // points to packet being serviced
    struct packet *buffer_last; // points to last packet in queue
    int buffer_fill; // number of packets in buffer
    int stream_index; // index of packet to be serviced
    Time window; //used to define how packets will be queued or dropped
     int streamPtrIndex = 1;
     int whileCondition;
     int ifCondition;

//int firstPacket=1;//first packet will never be lost so we dont need to check it the first packet is the first packet i.e. that its not lost

   
    // initialization
    buffer_first = stream; //starting at the beginning of the stream
    buffer_last = buffer_first;
    stream_ptr = buffer_first+1;

//window.tv_sec = buffer_first->routerBeginTime.tv_sec + servicetime.tv_sec;
//window.tv_usec = buffer_first->routerBeginTime.tv_usec + servicetime.tv_usec;
window.tv_sec = 0;
window.tv_usec = 0;


   for(stream_index=1;stream_index<num_Packets;buffer_first++,stream_index++){
            buffer_first->routerBeginTime.tv_sec = buffer_first->internetDispatchTime.tv_sec;//this packet has entered the router
           buffer_first->routerBeginTime.tv_usec = buffer_first->internetDispatchTime.tv_usec;
   }
//above, we are initializing their router entrance time. we could also easily add a line delay,
//i.e. that formula from class, delay = l/c + L/R or something like that. it would just be a constant factor
//not necessarily relevant but would make things more accurate. NOT a priority


   buffer_first = stream; //reinitializing


    for (stream_index = 1, buffer_fill = 1, buffer_first->packetLost = 0; stream_index < num_Packets; buffer_first++, stream_index++) { // may be  <=
        //NOTE: buffer_first->packetLost = 0 means that the first packet will never get lost, but this is ok
         //since this is the first packet in the system; it will never get lost! we just added this because
         //of the way some of our if conditions were written (I think that's why)

 
        if (buffer_first->packetLost == 1)
            continue;//this packet should not even be considered. move on through the list, increment our pointers

        if (buffer_first == stream_ptr) {//this is a special case that could happen if the above if statement is executed
            stream_ptr++;
            streamPtrIndex++;
        }
        //NOTE: I believe that there may be a invalid index issue here, if incrementing stream_index would invalidate
         //the for loop condition. I am not sure, ask Simon



        buffer_first->packetLost = 0;
        //packet isnt lost so far. just for initialization purposes






        //STEP 1: Define window: this just sets up the parameters for testing if a packet should be added to the queue
            if (buffer_first->routerBeginTime.tv_sec < window.tv_sec)
                ifCondition = 1;
 
            else if (buffer_first->routerBeginTime.tv_sec == window.tv_sec){
                if (buffer_first->routerBeginTime.tv_usec < window.tv_usec)
                     ifCondition = 1;
                else
                     ifCondition = 0;
               }

            else //We do not explicitly initialize Time window. In the first iteration, this else will occur, and cause window to initialize
                ifCondition = 0;

        if (ifCondition) {//Case 1: the next packet to be serviced arrived BEFORE the previous packet was serviced
            window.tv_sec = window.tv_sec + servicetime.tv_sec;
            window.tv_usec = window.tv_usec + servicetime.tv_usec;
        }

        else {//Case 2: the next packet to be serviced arrived AFTER the previous packet was serviced (I believe this would be an empty buffer)
printf("this should be first\n");
            window.tv_sec = buffer_first->routerBeginTime.tv_sec + servicetime.tv_sec;
            window.tv_usec = buffer_first->routerBeginTime.tv_usec + servicetime.tv_usec;
        }
printf("router begin is s: %d and us: %d\n",buffer_first->routerBeginTime.tv_sec,buffer_first->routerBeginTime.tv_usec);
printf("service time is s: %d and us: %d\n",servicetime.tv_sec,servicetime.tv_usec);
printf("window s is %d, window ms is %d\n",window.tv_sec,window.tv_usec);







        //STEP 2: We use our window condition defined in STEP 1 to determine which packets to place in the buffer

            if (stream_ptr->routerBeginTime.tv_sec < window.tv_sec)
                whileCondition = 1;
 
            else if (stream_ptr->routerBeginTime.tv_sec == window.tv_sec){
                if (stream_ptr->routerBeginTime.tv_usec < window.tv_usec)
                        whileCondition = 1;
                else
                        whileCondition = 0;

                }
            else
                whileCondition = 0;

//the whileCondition; if the next packet to be serviced will NOT be finished before other packets arrive, we must buffer packets in while loop
            while(whileCondition && streamPtrIndex < num_Packets) {

                 if (buffer_fill == buffersize)
                   stream_ptr->packetLost = 1; //drop packet; buffer is full
                
               else {                        //add packet to queue; buffer is not full
                       stream_ptr->packetLost = 0;
                       buffer_last = stream_ptr;
                       buffer_fill++;
                  }

                if(streamPtrIndex == num_Packets)
                        break; //NOTE: we are done...this if statement may not be needed bc of the while loop condition
              
               stream_ptr++;
                 streamPtrIndex++;



               //we now look to see if the NEXT packet will also need to be buffered; we retest the whileCondition
               //this could be condensed, but I think this makes it more clear what the conditions are

                 if (stream_ptr->routerBeginTime.tv_sec < window.tv_sec)
                            whileCondition = 1;
                else if (stream_ptr->routerBeginTime.tv_sec == window.tv_sec){
                        if (stream_ptr->routerBeginTime.tv_usec < window.tv_usec)
                                    whileCondition = 1;
                         else
                                   whileCondition = 0;
                   }
       
               else
                            whileCondition = 0;


          }    
         streamPtrIndex = 1;//reinitialize this for the next packet we service





   
        //STEP 3: service the packet
        buffer_first->routerEndTime.tv_sec = window.tv_sec;
        buffer_first->routerEndTime.tv_usec = window.tv_usec;//elvis has left the building
printf("router begin is s: %d and us: %d\n",buffer_first->routerBeginTime.tv_sec,buffer_first->routerBeginTime.tv_usec);
printf("router end is s: %d, router end is us: %d\n",buffer_first->routerEndTime.tv_sec,buffer_first->routerEndTime.tv_usec);

      if(buffer_fill != 0) 
            buffer_fill--;//NOTE: if there is only one packet in buffer, we dont want to decrement further...should double check on whether this is necessary


    }//end of for loop: we have serviced all the packets!


}


void printMuxedArrayRouter(struct packet *muxedPacketArray, int totalNumberOfPackets)
{
    int packetCounter = 0;
    struct packet *temp;
    FILE * pFile;
    pFile = fopen ("resultsOfRouter.txt","wb");
  
    for (packetCounter = 0; packetCounter < totalNumberOfPackets; packetCounter++)
    {
        temp = muxedPacketArray + packetCounter;

        fprintf(pFile,"\nPacket %d:\n",packetCounter+1);
        fprintf(pFile, "routerBeginTime(s): %d\t\t routerBeginTime(us): %d\t\t source: %c\t\t BRAS: %d\t DSLAM: %d\t User: %d\n",
                        temp->routerBeginTime.tv_sec, temp->routerBeginTime.tv_usec, temp->source, temp->brasNumber, temp->dslamNumber, temp->userNumber);
            fprintf(pFile, "routerEndTime(s):   %d\t\t routerEndTime(us):   %d\t\t LOST: %d\t\t \n",
                                      temp->routerEndTime.tv_sec, temp->routerEndTime.tv_usec, temp->packetLost);
    }
    fclose (pFile);
}

void printMuxedArraybras(struct packet *muxedPacketArray, int totalNumberOfPackets)
{
    int packetCounter = 0;
    struct packet *temp;
    FILE * pFile;
    pFile = fopen ("resultsOfbras.txt","wb");
  
    for (packetCounter = 0; packetCounter < totalNumberOfPackets; packetCounter++)
    {
        temp = muxedPacketArray + packetCounter;
	
        fprintf(pFile,"\nPacket %d:\n",packetCounter+1);
        fprintf(pFile, "brasBeginTime(s): %d\t\t brasBeginTime(us): %d\t\t source: %c\t\t BRAS: %d\t DSLAM: %d\t User: %d\n",
                        temp->brasBeginTime.tv_sec, temp->brasBeginTime.tv_usec, temp->source, temp->brasNumber, temp->dslamNumber, temp->userNumber);
            fprintf(pFile, "brasEndTime(s):   %d\t\t brasEndTime(us):   %d\t\t LOST: %d\t\t \n",
                                      temp->brasEndTime.tv_sec, temp->brasEndTime.tv_usec, temp->packetLost);
    }
    fclose (pFile);
}

void lindleysBras(struct packet * stream, const Time servicetime, int buffersize, int num_Packets) {

    struct packet *stream_ptr;    // points to a packet in the incoming stream of packets
    struct packet *buffer_first; // points to packet being serviced
    struct packet *buffer_last; // points to last packet in queue
    int buffer_fill; // number of packets in buffer
    int stream_index; // index of packet to be serviced
    Time window; //used to define how packets will be queued or dropped
     int streamPtrIndex = 1;
     int whileCondition;
     int ifCondition;

//int firstPacket=1;//first packet will never be lost so we dont need to check it the first packet is the first packet i.e. that its not lost

   
    // initialization
    buffer_first = stream; //starting at the beginning of the stream
    buffer_last = buffer_first;
    stream_ptr = buffer_first+1;

//window.tv_sec = buffer_first->routerBeginTime.tv_sec + servicetime.tv_sec;
//window.tv_usec = buffer_first->routerBeginTime.tv_usec + servicetime.tv_usec;
window.tv_sec = 0;
window.tv_usec = 0;


   for(stream_index=1;stream_index<num_Packets;buffer_first++,stream_index++){
            buffer_first->brasBeginTime.tv_sec = buffer_first->internetDispatchTime.tv_sec;//this packet has entered the router
           buffer_first->brasBeginTime.tv_usec = buffer_first->internetDispatchTime.tv_usec;
   }
//above, we are initializing their router entrance time. we could also easily add a line delay,
//i.e. that formula from class, delay = l/c + L/R or something like that. it would just be a constant factor
//not necessarily relevant but would make things more accurate. NOT a priority


   buffer_first = stream; //reinitializing


    for (stream_index = 1, buffer_fill = 1, buffer_first->packetLost = 0; stream_index < num_Packets; buffer_first++, stream_index++) { // may be  <=
        //NOTE: buffer_first->packetLost = 0 means that the first packet will never get lost, but this is ok
         //since this is the first packet in the system; it will never get lost! we just added this because
         //of the way some of our if conditions were written (I think that's why)

 
        if (buffer_first->packetLost == 1)
            continue;//this packet should not even be considered. move on through the list, increment our pointers

        if (buffer_first == stream_ptr) {//this is a special case that could happen if the above if statement is executed
            stream_ptr++;
            streamPtrIndex++;
        }
        //NOTE: I believe that there may be a invalid index issue here, if incrementing stream_index would invalidate
         //the for loop condition. I am not sure, ask Simon



        buffer_first->packetLost = 0;
        //packet isnt lost so far. just for initialization purposes






        //STEP 1: Define window: this just sets up the parameters for testing if a packet should be added to the queue
            if (buffer_first->brasBeginTime.tv_sec < window.tv_sec)
                ifCondition = 1;
 
            else if (buffer_first->brasBeginTime.tv_sec == window.tv_sec){
                if (buffer_first->brasBeginTime.tv_usec < window.tv_usec)
                     ifCondition = 1;
                else
                     ifCondition = 0;
               }

            else //We do not explicitly initialize Time window. In the first iteration, this else will occur, and cause window to initialize
                ifCondition = 0;

        if (ifCondition) {//Case 1: the next packet to be serviced arrived BEFORE the previous packet was serviced
            window.tv_sec = window.tv_sec + servicetime.tv_sec;
            window.tv_usec = window.tv_usec + servicetime.tv_usec;
        }

        else {//Case 2: the next packet to be serviced arrived AFTER the previous packet was serviced (I believe this would be an empty buffer)
printf("this should be first\n");
            window.tv_sec = buffer_first->brasBeginTime.tv_sec + servicetime.tv_sec;
            window.tv_usec = buffer_first->brasBeginTime.tv_usec + servicetime.tv_usec;
        }
printf("router begin is s: %d and us: %d\n",buffer_first->brasBeginTime.tv_sec,buffer_first->brasBeginTime.tv_usec);
printf("service time is s: %d and us: %d\n",servicetime.tv_sec,servicetime.tv_usec);
printf("window s is %d, window ms is %d\n",window.tv_sec,window.tv_usec);







        //STEP 2: We use our window condition defined in STEP 1 to determine which packets to place in the buffer

            if (stream_ptr->brasBeginTime.tv_sec < window.tv_sec)
                whileCondition = 1;
 
            else if (stream_ptr->brasBeginTime.tv_sec == window.tv_sec){
                if (stream_ptr->brasBeginTime.tv_usec < window.tv_usec)
                        whileCondition = 1;
                else
                        whileCondition = 0;

                }
            else
                whileCondition = 0;

//the whileCondition; if the next packet to be serviced will NOT be finished before other packets arrive, we must buffer packets in while loop
            while(whileCondition && streamPtrIndex < num_Packets) {

                 if (buffer_fill == buffersize)
                   stream_ptr->packetLost = 1; //drop packet; buffer is full
                
               else {                        //add packet to queue; buffer is not full
                       stream_ptr->packetLost = 0;
                       buffer_last = stream_ptr;
                       buffer_fill++;
                  }

                if(streamPtrIndex == num_Packets)
                        break; //NOTE: we are done...this if statement may not be needed bc of the while loop condition
              
               stream_ptr++;
                 streamPtrIndex++;



               //we now look to see if the NEXT packet will also need to be buffered; we retest the whileCondition
               //this could be condensed, but I think this makes it more clear what the conditions are

                 if (stream_ptr->brasBeginTime.tv_sec < window.tv_sec)
                            whileCondition = 1;
                else if (stream_ptr->brasBeginTime.tv_sec == window.tv_sec){
                        if (stream_ptr->brasBeginTime.tv_usec < window.tv_usec)
                                    whileCondition = 1;
                         else
                                   whileCondition = 0;
                   }
       
               else
                            whileCondition = 0;


          }    
         streamPtrIndex = 1;//reinitialize this for the next packet we service





   
        //STEP 3: service the packet
        buffer_first->brasEndTime.tv_sec = window.tv_sec;
        buffer_first->brasEndTime.tv_usec = window.tv_usec;//elvis has left the building
printf("router begin is s: %d and us: %d\n",buffer_first->brasBeginTime.tv_sec,buffer_first->brasBeginTime.tv_usec);
printf("router end is s: %d, router end is us: %d\n",buffer_first->brasEndTime.tv_sec,buffer_first->brasEndTime.tv_usec);

      if(buffer_fill != 0) 
            buffer_fill--;//NOTE: if there is only one packet in buffer, we dont want to decrement further...should double check on whether this is necessary


    }//end of for loop: we have serviced all the packets!


}




int main() {



    Time routerservicetime;
    routerservicetime.tv_sec = 0;
    routerservicetime.tv_usec = 50;//we can set this to whatever we want

 	 Time brasservicetime;
    brasservicetime.tv_sec = 0;
    brasservicetime.tv_usec = 50;//we can set this to whatever we want

    NUM_BELL_PACKETS = NUM_USER_PER_DSLAM * NUM_BELL_DSLAM * NUM_OF_PACKET_PER_BELL_USER;
    NUM_TEX_PACKETS = NUM_USER_PER_DSLAM * NUM_TEX_DSLAM * NUM_OF_PACKET_PER_TEX_USER;
    printf("users per dslam= %d\n", NUM_USER_PER_DSLAM);
    printf("Bell:\n dslams #= %d,packet per user#= %d, total packets #= %d\n",NUM_BELL_DSLAM, NUM_OF_PACKET_PER_BELL_USER,NUM_BELL_PACKETS);
    printf("Techsavy:\n dslams #= %d,packet per user#= %d, total packets #= %d\n",NUM_TEX_DSLAM, NUM_OF_PACKET_PER_TEX_USER,NUM_TEX_PACKETS);

    printf("allocating memory...\n");
    fflush(stdout);
    initializePacketArrayForEachService();
    printf("populating packet arrays for each provider...\n");
    fflush(stdout);
    initializeEverythingElseForAllServices();

    int num_muxed_packet_array = NUM_BELL_PACKETS + NUM_TEX_PACKETS;
    struct packet *muxedPacketArray;
    muxedPacketArray = (struct packet*) malloc(num_muxed_packet_array * sizeof(struct packet));
    if (muxedPacketArray == NULL) {
        printf("ERROR: malloc()\n");
        return -1;
    }

    printf("mux() ...\n");
    fflush(stdout);
    int totalNumberOfPackets = mux(M, N, NULL, NULL, muxedPacketArray);
    printf("print muxxed data ...\n");
    printMuxedArrayInternet(muxedPacketArray, totalNumberOfPackets);
	 
	 lindleysRouter(muxedPacketArray, routerservicetime, 10, 1000);//buffer of 10, 100 packets
	 printMuxedArrayRouter(muxedPacketArray, 1000);//michael's function

		struct packet *temp;
		int packetCounter;
		for  (packetCounter = 0; packetCounter < TOTAL_PACKS; packetCounter++){
			  temp = muxedPacketArray + packetCounter;
			  temp->brasBeginTime.tv_sec = temp->routerEndTime.tv_sec;
			  temp->brasBeginTime.tv_usec = temp->routerEndTime.tv_usec;
		}

	 //set bras begin times to router end times	 
	 lindleysBras(muxedPacketArray, brasservicetime, 10, 1000);
	 printMuxedArraybras(muxedPacketArray, 1000);

	 /*DSLAM
		 demuxmuxedPacketArray //outputs two separate arrays
		 lindleysarray1
		 lindleysarray2
	*/


	 //demux();
	 //lindleysDslam1(muxedPacketArray, dslamservicetime, 10, 1000);
	 //lindleysDslam2(muxedPacketArray, dslamservicetime, 10, 1000);
	 //printDSLAMdataCSV();
	 //printDslamterminal(muxedPacketArray, 1000);	

    /////////////////////////////////////////////////////////// main   demux  ////////////////////////////////////////////////////////////////////

    // put here to make things easy, a function would require some sort of triple pointer
    
    // NOTE: in packetArray dslams are from 0 to total number of dslams (minus 1)
    // But the indexing for BOTH demuxxed dslam arrays starts 0   

    printf("demux() ...\n");
    fflush(stdout);
    int i;
    struct packet TEXpacketArray[NUM_TEX_DSLAM][NUM_OF_PACKET_PER_TEX_USER * NUM_USER_PER_DSLAM];
    struct packet BELLpacketArray[NUM_BELL_DSLAM][NUM_OF_PACKET_PER_BELL_USER * NUM_USER_PER_DSLAM];
    int TEXindx[NUM_TEX_DSLAM];
    int BELLindx[NUM_BELL_DSLAM];
    //initialize index counters
    for (i = 0; i < NUM_TEX_DSLAM; i++) {
        TEXindx[i] = 0;
    }
    for (i = 0; i < NUM_BELL_DSLAM; i++) {
        BELLindx[i] = 0;
    }

    //go through packetArray, see which dslam it's from, put it where it belongs
    for (i = 0; i < NUM_BELL_PACKETS + NUM_TEX_PACKETS; i++) 
    {
        if (muxedPacketArray[i].dslamNumber < NUM_TEX_DSLAM) {
            TEXpacketArray[muxedPacketArray[i].dslamNumber][TEXindx[muxedPacketArray[i].dslamNumber]] = muxedPacketArray[i];
            //printf("%d,%d ",muxedPacketArray[i].userNumber,TEXpacketArray[muxedPacketArray[i].dslamNumber][TEXindx[muxedPacketArray[i].dslamNumber]].userNumber);
            TEXindx[muxedPacketArray[i].dslamNumber]++;
        } 
	else {
            BELLpacketArray[muxedPacketArray[i].dslamNumber-NUM_TEX_DSLAM][BELLindx[muxedPacketArray[i].dslamNumber-NUM_TEX_DSLAM]] = muxedPacketArray[i];
            BELLindx[muxedPacketArray[i].dslamNumber-NUM_TEX_DSLAM]++;
        }
    }
    //////////////////////////////////////////////////// end of demux ///////////////////////////////////////////////////////////////////


    // put code for lin here: vvvvv


    // end of code of lin ^^^^^^^^^

    //////////////////////////////////// write demux packets to files
    printf("print demuxxed data ...\n");
    fflush(stdout);
    int j;
    char fileName[20];
    FILE *pFile = NULL;
    for (j = 0; j < NUM_TEX_DSLAM; j++) {

        memset(fileName, 0, 20);
        sprintf(fileName, "t%d.txt", j); // create a file for TEX DSLAM
        pFile = fopen(fileName, "w");

        for (i = 0; i < NUM_USER_PER_DSLAM * NUM_OF_PACKET_PER_TEX_USER; i++) {
	    // NOTE: add additional times you want to print to file here !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            fprintf(pFile, "%d, %d, %c, %d, %d, %d\n",   TEXpacketArray[j][i].internetDispatchTime.tv_sec, TEXpacketArray[j][i].internetDispatchTime.tv_usec, TEXpacketArray[j][i].source, TEXpacketArray[j][i].brasNumber, TEXpacketArray[j][i].dslamNumber, TEXpacketArray[j][i].userNumber);
        }
        fclose(pFile);
    }
    for (j = 0; j < NUM_BELL_DSLAM; j++) {
        memset(fileName, 0, 20);
        sprintf(fileName, "b%d.txt", j);  // create a file for BELL DSLAM
        pFile = fopen(fileName, "w");

        for (i = 0; i < NUM_USER_PER_DSLAM * NUM_OF_PACKET_PER_BELL_USER; i++) {
            // NOTE: add additional times you want to print to file here !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            fprintf(pFile, "%d, %d, %c, %d, %d, %d\n", BELLpacketArray[j][i].internetDispatchTime.tv_sec, BELLpacketArray[j][i].internetDispatchTime.tv_usec, BELLpacketArray[j][i].source, BELLpacketArray[j][i].brasNumber, BELLpacketArray[j][i].dslamNumber,  BELLpacketArray[j][i].userNumber);
        }
        fclose(pFile);
    }
	//////////////////////////////////// end of write to file


      
    return 0;
}

